package com.xzbd.springbootmybatiesdm.controller;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import javax.servlet.http.HttpServletResponse;

import com.xzbd.springbootmybatiesdm.common.response.R;
import com.xzbd.springbootmybatiesdm.config.UploadConfig;
import com.xzbd.springbootmybatiesdm.domain.Event;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpRequest;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.client.ClientHttpRequestExecution;
import org.springframework.http.client.ClientHttpRequestInterceptor;
import org.springframework.http.client.ClientHttpResponse;
import org.springframework.http.client.support.HttpRequestWrapper;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.StreamUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import lombok.extern.slf4j.Slf4j;


@Slf4j
@RestController()
@RequestMapping("rest")
public class RestTemplateController{

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private UploadConfig uploadConfig;

    private String URI = "http://localhost:8888/api/";

    /**
     * getForObject 示例 
     * @return
     */
    @GetMapping("get-event-list")
    public R getEventList(){
        // 获取事件列表
        Map<String,Object> params = new HashMap<>();
        params.put("page", 1);
        params.put("limit", 10);
        String urlParams = "?page={page}&limit={limit}";
        return restTemplate.getForObject(URI + "/event/list" + urlParams, R.class, params);
    }

    /**
     * getForEntity 示例
     * @return
     */
    @GetMapping("get-event-list2")
    public R getEventList2(){
        // 获取事件列表
        Map<String,Object> params = new HashMap<>();
        params.put("page", 1);
        params.put("limit", 10);
        String urlParams = "?page={page}&limit={limit}";
        ResponseEntity<R> entity = restTemplate.getForEntity(URI + "/event/list" + urlParams, R.class, params);
        log.info("<<<<<<<<<<< entity : " + entity.toString());
        if(entity.getStatusCode().value() == 200){
            return entity.getBody();
        }else{
            return R.error("链接失败");
        }
    }

    /**
     * postForObject + formData 示例 
     * @param event
     * @return
     */
    @GetMapping(value="add-event-1")
    public R addEventFormObject() {
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, String> params= new LinkedMultiValueMap<String, String>();
        //  也支持中文
        params.add("ruleId", "111");
        params.add("ruleName", "AAA");
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers);

         return restTemplate.postForObject(URI + "event/add/form", requestEntity, R.class);
    }
    /**
     * postForEntity + formData 示例 
     * @param event
     * @return
     */
    @GetMapping(value="add-event-2")
    public R addEventFormEntity() {
        HttpHeaders headers = new HttpHeaders();
        //  请勿轻易改变此提交方式，大部分的情况下，提交方式都是表单提交
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
        //  封装参数，千万不要替换为Map与HashMap，否则参数无法传递
        MultiValueMap<String, String> params= new LinkedMultiValueMap<String, String>();
        //  也支持中文
        params.add("ruleId", "222");
        params.add("ruleName", "BBB");
        HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<MultiValueMap<String, String>>(params, headers);

        ResponseEntity<R> postForEntity = restTemplate.postForEntity(URI + "event/add/form", requestEntity, R.class);
        int statusCode = postForEntity.getStatusCodeValue();
        if(statusCode==200){
            return postForEntity.getBody();
        }else{
            return R.error("链接失败");
        }
    }
    /**
     * postForObject + JSON 示例 
     * @param event
     * @return
     */
    @GetMapping(value="add-event-3")
    public R addEventJsonObject() {
        Event event = new Event();
        event.setRuleId("333");
        event.setRuleName("CCC");
         return restTemplate.postForObject(URI + "event/add/json", event, R.class);
    }
    /**
     * postForEntity + JSON 示例 
     * @param event
     * @return
     */
    @GetMapping(value="add-event-4")
    public R addEventJsonEntity() {
        Event event = new Event();
        event.setRuleId("444");
        event.setRuleName("DDD");
        ResponseEntity<R> postForEntity = restTemplate.postForEntity(URI + "event/add/json", event, R.class);
        int statusCode = postForEntity.getStatusCodeValue();
        if(statusCode==200){
            return postForEntity.getBody();
        }else{
            return R.error("链接失败");
        }
    }

    // ===============================
    // 文件上传属于 form 表单提交 

    /**
     * 文件上传 + postForEntity
     * @return
     */
    @GetMapping(value="upload-1")
    public R uploaadObj() {
        // 文件路径
        String filePath = uploadConfig.getDocPath() + "/ed7dda70-90e6-47a7-90b7-24411fed9313.zip";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        headers.setConnection("Keep-Alive");
        headers.setCacheControl("no-cache");
        FileSystemResource resource = new FileSystemResource(new File(filePath));
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
		param.add("file", resource);
        param.add("fileName", "test.txt");

        // 发送请求 
        return restTemplate.postForObject(URI + "/upload/file", param, R.class);
        
    }
    public static void main(String[] args) {
        RestTemplate restTemplate = new RestTemplate();
        String url = "http://localhost:8888/api/upload/file";
        String filePath = "/media/xzbd/tmp/spring-boot-mybaties-dm/upload/doc/ed7dda70-90e6-47a7-90b7-24411fed9313.zip";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        headers.setConnection("Keep-Alive");
        headers.setCacheControl("no-cache");
        FileSystemResource resource = new FileSystemResource(new File(filePath));
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
		param.add("file", resource);
        param.add("fileName", "test.txt");
        R r = restTemplate.postForObject(url, param, R.class);
        System.out.println(r.toString());
        
    }
    /**
     * 文件上传 +  postForEntity
     * @return
     */
    @GetMapping(value="upload-2")
    public R uploaadEntity() {
        String filePath = uploadConfig.getDocPath() + "/ed7dda70-90e6-47a7-90b7-24411fed9313.zip";
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        headers.setConnection("Keep-Alive");
        headers.setCacheControl("no-cache");
        FileSystemResource resource = new FileSystemResource(new File(filePath));
        MultiValueMap<String, Object> param = new LinkedMultiValueMap<>();
		param.add("file", resource);
        param.add("fileName", "test.txt");
        ResponseEntity<R> postForEntity = restTemplate.postForEntity(URI + "/upload/file", param, R.class);
        int statusCode = postForEntity.getStatusCodeValue();
        if(statusCode==200){
            return postForEntity.getBody();
        }else{
            return R.error("链接失败");
        }
    }
    /**
     * 文件下载 + obj 
     */
    @GetMapping(value="download-1")
    public R downloadObject(HttpServletResponse response) {
        ClientHttpRequestInterceptor acceptHeaderZip = new AcceptHeaderHttpRequestInterceptor(
            "application/zip");
		List<ClientHttpRequestInterceptor> clist = new ArrayList<ClientHttpRequestInterceptor>();
		clist.add(acceptHeaderZip);
        restTemplate.setInterceptors(clist);

        byte[] fileByte = restTemplate.getForObject(URI + "/download/file", byte[].class);

        try {
            StreamUtils.copy(fileByte, response.getOutputStream());
            response.getOutputStream().flush();
            return R.ok();
        } catch (IOException e) {
            log.error("下载文件失败 <<<<<<<<<<<<<<< ", e.getMessage(), e.getCause());
            return R.error();
        }
    }
    
    /**
     * 下载文件 + entity
     * 
     * @return
     * @throws IOException
     */
    @GetMapping(value = "download-2")
    public R downloadEntity(HttpServletResponse response) throws IOException {
        ClientHttpRequestInterceptor acceptHeaderZip = new AcceptHeaderHttpRequestInterceptor(
            "application/zip");
		List<ClientHttpRequestInterceptor> clist = new ArrayList<ClientHttpRequestInterceptor>();
		clist.add(acceptHeaderZip);
        restTemplate.setInterceptors(clist);
        ResponseEntity<byte[]> entity = restTemplate.getForEntity(URI + "/download/file", byte[].class);
        if(entity.getStatusCodeValue() == 200 ){
            // 设置相关格式
		response.setContentType("application/force-download");
		// 设置下载后的文件名以及header
		response.addHeader("Content-disposition", "attachment;fileName=abcdXZAL.zip");
            byte[] filebyte = entity.getBody();
            StreamUtils.copy(filebyte, response.getOutputStream());
            return R.ok();
        }else{
            return R.error();
        }
        
    }
    /**
     * 下载文件 + exchange
     * 
     * @return
     * @throws IOException
     */
    @GetMapping(value = "download-3")
    public void downloadExchange(HttpServletResponse response) throws IOException {
        HttpHeaders headers = new HttpHeaders();
        HttpEntity<Resource> httpEntity = new HttpEntity<Resource>(headers);
        ResponseEntity<byte[]> serverResponse = restTemplate.exchange(URI + "/download/file", HttpMethod.GET,
                httpEntity, byte[].class);
        log.info("===状态码================");
        log.info(">> {}", serverResponse.getStatusCodeValue());
        log.info("===返回信息================");
        log.info(">> {}", serverResponse.getHeaders().getContentType());
        log.info(">> {}", serverResponse.getHeaders().getContentType().getSubtype());
        response.setHeader("Content-disposition", "attachment;fileName=abcd你好.zip");
        response.setCharacterEncoding("UTF-8");
        response.setLocale(new Locale("zh","CN"));
        response.setContentType("text/html;charset=utf-8");
        StreamUtils.copy(serverResponse.getBody(), response.getOutputStream());
        response.getOutputStream().flush();
        
        
    }


    /**
     * 拦截器
     */
    class AcceptHeaderHttpRequestInterceptor implements ClientHttpRequestInterceptor {
        private final String headerValue;

        public AcceptHeaderHttpRequestInterceptor(String headerValue) {
            this.headerValue = headerValue;
        }

        @Override
        public ClientHttpResponse intercept(HttpRequest request, byte[] body,
                ClientHttpRequestExecution execution) throws IOException {

            HttpRequestWrapper requestWrapper = new HttpRequestWrapper(request);
            List<MediaType> mytype = new ArrayList<MediaType>();
            mytype.add(MediaType.valueOf(headerValue));
            requestWrapper.getHeaders().setAccept(mytype);

            return execution.execute(requestWrapper, body);
        }
    }


}